package com.sqsf.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Controller
public class MyController {

    //默认情况下使用页面跳转
    //跳转的页面为视图解析器前缀+方法名+视图解析器后缀
    //WEB-INF/views/a.jsp
    @RequestMapping("/a")
    public void a(){
        System.out.println("aaaaaa");
    }



    //springMVC数据响应
    //跳转页面-字符串跳转
    //为方法书写返回值 返回值的字符串就是定义的名称
    //跳转的页面为视图解析器前缀+返回值+视图解析器后缀
    //如果没有视图解析器 我们需要手动添加页面路径
    ///WEB-INF/views/a.jsp
    //返回字符串的形式也是可以携带数据的 借助servlet原有的方式
    @RequestMapping("/res1")
    public String response1(HttpServletRequest request){
        System.out.println("springMVC数据响应-跳转页面-字符串跳转");
        request.setAttribute("msg","data!!");
        return  "a";
    }

    //跳转页面-ModelAndView视图对象跳转
    //ModelAndView是springMVC提供的保存视图与数据的工具类
    //可以理解为处理器再处理完请求后 会将需要跳转页面的字符串与数据存入该对象
    //将该对象返回给中央处理器 中央处理器获取页面字符串基于视图解析器 得到对应的具体页面
    //然后将页面与数据整合 返回给客户端
    @RequestMapping("/res2")
    public ModelAndView response2(ModelAndView mv){
        System.out.println("springMVC数据响应-跳转页面-ModelAndView跳转");
        //参数列表的对象 会交由spring进行处理 我们可以直接使用
        mv.setViewName("a");
        mv.addObject("msg","data response!");
        return  mv;
    }

    //返回数据-返回字符串数据
    //将返回字符串直接在页面显示
    //如果直接返回数据 会使用视图解析器解析为视图
    //需要书写注解告诉视图解析器这是直接返回的数据 不要解析
    @RequestMapping("/res3")
    @ResponseBody
    public String response3(){
        System.out.println("springMVC数据响应-返回数据-返回字符串数据1");
        return  "直接返回数据";
    }
    //如上代码底层的原理是使用response对象getWriter方法将内容写入到页面
    @RequestMapping("/res4")
    public void response4(HttpServletResponse response) throws IOException {
        System.out.println("springMVC数据响应-返回数据-返回字符串数据2");
        response.getWriter().println("直接返回数据");
    }

    //json字符串也是一种特殊格式的字符串 也可以拼接返回
    @RequestMapping(value="/res5")
    @ResponseBody
    public String res5() throws IOException {
        System.out.println("springMVC数据响应-返回数据-返回字符串数据3");
        return "{\"username\":\"zhangsan\",\"age\":18}";
    }

    //springMVC中有各种组件工具 书写 <mvc:annotation-driven/>进行自动配置
    //可以自动将对象或集合转换为json数据并返回
    @RequestMapping(value="/res6")
    @ResponseBody
    public User res6() throws IOException {
        System.out.println("springMVC数据响应-返回数据-返回对象");
        User u=new User(1,"zhangsan",19);
        return u;
    }
    @RequestMapping(value="/res7")
    @ResponseBody
    public List<User> res7() throws IOException {
        System.out.println("springMVC数据响应-返回数据-返回集合");
        ArrayList<User> list=new ArrayList<>();
        list.add(new User(1,"zgsan",19));
        list.add(new User(2,"zgsan2",29));
        list.add(new User(3,"zgsan3",39));
        return list;
    }


    //SpringMVC的数据请求
    //使用springMVC获取客户端请求携带的数据

    //常用类型(基本数据类型以及其包装类/字符串)参数的获取
    //数据在网络上传输本质是二进制流 进行获取获取的是字符串
    //所以之前在servlet中我们虽然可以获取请求的参数 但是有时候需要进行类型转换后才能使用
    //但是 springMVC获取请求参数就没有这个问题

    //SpringMVC会自动获取方法请求参数列表中 参数名称对应的数据并注入
    //并且自动进行对应的类型转换(注意 如果数据无法转换会报错)
    @RequestMapping("/res8")
    public void res8(String name,int age){
        System.out.println(name+"|"+age);
    }
    //如上代码可以进行请求参数的获取  但是 如果参数的名称不匹配或没有携带数据
    //都可能导致失败
    //RequestParam注解可以帮助我们解决这个问题 使用设置的name进行数据的获取
    //一旦使用RequestParam注解那么请求时 必须携带对应的数据
    //因为拥有必填属性 默认为true
    //可以进一步使用属性required = false,defaultValue="值"
    //可以设置请求时如果没有携带指定数据 使用默认值赋值
    @RequestMapping("/res9")
    public void res9(@RequestParam("uname") String name,@RequestParam(value = "uage",required = false,defaultValue = "0") int age){
        System.out.println(name+"|"+age);
    }

    //SpringMVC能做到的不止这些
    //自定义类型数据获取
    //在进行开发时例如注册需要获取数据并将其存入对应的对象
    //在之前我们先依次获取对应的属性值 然后在方法体中进行对象的创建与赋值
    //SpringMVC借助spring与基础的数据获取 也可以自动实现这个功能
//    @RequestMapping("/res10")
//    public void res10(int id,String name,int age){
//        User u=new User(id,name,age);
//        System.out.println(u);
//    }
    //SpringMVC会自动创建对象 并调用对象的setter方法将数据存入
    @RequestMapping("/res10")
    public void res10(User u){
        System.out.println(u);
    }



    //数组类型数据的获取
    //在之前进行servlet参数获取时 针对于请求一个name对应多个数据的情况
    //额外提供了对应的方法 以数组的形式进行数据的获取
    //springMVC在此基础上 也可以对象数组的数据进行获取与类型转换
    //例如 批量删除时 会传入多个id数据
    @RequestMapping("/res11")
    public void res11(int[] id){
        System.out.println(Arrays.toString(id));
    }

    //以上都是基于JavaWeb学习时 基于servlet对应的请求对象提供的API进行封装
    //现在项目大多使用前后端分离(前端项目单独运行  后端项目单独运行
    //前端请求后端 后端仅返回数据  前后端交互使用 json格式数据 )

    //使用集合获取请求携带的json数组对象
    //使用@RequestBody注解 告诉SpringMVC 这个参数获取的是请求的json数据
    @RequestMapping(value = "/res12",method = RequestMethod.POST)
    public void res12(@RequestBody List<User> userList){
        System.out.println(userList);
    }
    //除了批量创建外 前端没有必要发送包含大量数据的json 一般进行仅发送一个对象的数据即可
    @RequestMapping(value = "/res13",method = RequestMethod.POST)
    public void res12(@RequestBody User user){
        System.out.println(user);
    }
}